﻿using System;
using System.Collections;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web.ModelBinding;
using System.Web.Routing;

namespace Quintsys.BootstrapSupport
{
    public static class DefaultScaffoldingExtensions
    {
        public static string GetControllerName(this Type controllerType)
        {
            return controllerType.Name.Replace("Controller", String.Empty);
        }

        public static string GetActionName(this LambdaExpression actionExpression)
        {
            return ((MethodCallExpression)actionExpression.Body).Method.Name;
        }

        public static PropertyInfo[] VisibleProperties(this IEnumerable model)
        {
            var elementType = model.GetType().GetElementType() ?? model.GetType().GetGenericArguments()[0];
            return elementType.GetProperties()
                              .Where(info => info.Name != elementType.IdentifierPropertyName())
                              .ToArray();
        }

        public static PropertyInfo[] VisibleProperties(this object model)
        {
            return model.GetType().GetProperties().Where(info => info.Name != model.IdentifierPropertyName()).ToArray();
        }

        public static RouteValueDictionary GetIdValue(this object model)
        {
            var v = new RouteValueDictionary
                {
                    {
                        model.IdentifierPropertyName(),
                        model.GetId()
                    }
                };
            return v;
        }

        public static object GetId(this object model)
        {
            return model.GetType().GetProperty(model.IdentifierPropertyName()).GetValue(model, new object[0]);
        }

        public static string IdentifierPropertyName(this object model)
        {
            return IdentifierPropertyName(model.GetType());
        }

        public static string IdentifierPropertyName(this Type type)
        {
            if (type.GetProperties().Any(info => info.PropertyType.AttributeExists<KeyAttribute>()))
            {
                return type.GetProperties()
                           .First(info => info.PropertyType.AttributeExists<KeyAttribute>())
                           .Name;
            }
            if (type.GetProperties().Any(p => p.Name.Equals("id", StringComparison.CurrentCultureIgnoreCase)))
            {
                return type.GetProperties()
                           .First(p => p.Name.Equals("id", StringComparison.CurrentCultureIgnoreCase))
                           .Name;
            }

            return string.Empty;
        }

        public static string GetLabel(this PropertyInfo propertyInfo)
        {
            if (propertyInfo == null)
            {
                return null;
            }

            if (propertyInfo.DeclaringType == null)
            {
                return null;
            }

            var meta = ModelMetadataProviders.Current.GetMetadataForProperty(null, propertyInfo.DeclaringType,
                                                                             propertyInfo.Name);
            return meta.GetDisplayName();
        }

        public static string ToSeparatedWords(this string value)
        {
            return Regex.Replace(value, "([A-Z][a-z])", " $1").Trim();
        }
    }
}